
.text
.global main 
.global p1
.global p2
        .global writeint
        ## void writeint(int n)
        ## writes n on sysout

	
        .global readint
        ## int readint()
        ## reads an integer from sysin
        ## return value is in eax
	
        .global writestr
        ## void writestr(char[] str, int n)
        ## writes n characters from str on sysout
	
        .global writeln
        ## void writeln()
        ## writes a newline character on sysout
	
        .global exit            
        ## void exit(int n)
        ## terminates execution with error code n
main:
	movl    	%esp, 	%ebp      	#set base pointer
	subl	$4, 	%esp	# declare variable x
	movl 	$123, -4(%ebp)	# x=1
	
	push	-4(%ebp) 		# prepare for function call
	call 	p1
	addl	$4,		%esp	#reset stack pointer
	
	push	$0
	call 	exit
	
p1:
	pushl   %ebp            # save old base pointer
    pushl   %ebx            # save ebx
    pushl   %edi            # save edi
    movl    %esp, %ebp      # set base pointer
    
    push	%ebp
    movl	8(%ebp), %ebp		#restore old base pointer
	call	p2
	pop 	%ebp      		#restore current base pointer
	
	movl    %ebp, %esp      # restore stack pointer
	popl    %edi            # restore edi
    popl    %ebx            # restore ebx
    popl    %ebp            # restore base pointer					
	ret
p2:
	pushl   %ebp            # save old base pointer
    pushl   %ebx            # save ebx
    pushl   %edi            # save edi
    movl    %esp, %ebp      # set base pointer
    
	push	%ebp			#save current bp
    movl	8(%ebp), %ebp		#use old bp
    
	push	-4(%ebp)		#setup function call (using old bp x)
	call 	writeint			
	addl	$4, 	%esp	#reset stack pointer
	
	popl		%ebp		#restore current bp
	
	movl    %ebp, %esp      # restore stack pointer
	popl    %edi            # restore edi
    popl    %ebx            # restore ebx
    popl    %ebp            # restore base pointer
	ret


writeint:
         pushl   %ebp            # save old base pointer
         pushl   %ebx            # save ebx
         pushl   %edi            # save edi
         movl    %esp, %ebp      # set base pointer
         movl    16(%ebp), %eax  # copy argument to eax 
         movl    $10, %ecx       # set divisor to 10
         subl    $12, %esp       # allocate for local string
         movl    %ebp, %edi      # set edi 
         cmpl    $0, %eax        # argument negative?
         jge     writedigit
         negl    %eax            # negate
writedigit:  
         movl    $0, %edx        # set up for 64 bit division
         idivl   %ecx            # divide edx:aex by 10
         addl    $'0, %edx       # ascii digit in edx
         decl    %edi            # push ...
         movb    %dl, (%edi)     # digit 
         cmpl    $0, %eax        # quotient=0 ?
         jg      writedigit
         cmpl    $0, 16(%ebp)    # argument negative?
         jge     nosign
         decl    %edi            # push ...
         movb    $'-, (%edi)     # '-'
nosign:  movl    %ebp, %edx
         subl    %edi, %edx      # third argument: string length
         movl    %edi, %ecx      # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         movl    %ebp, %esp      # restore stack pointer
         popl    %edi            # restore edi
         popl    %ebx            # restore ebx
         popl    %ebp            # restore base pointer
         ret                     # return
         
readint:
         pushl   %ebp            # save old base pointer
         pushl   %ebx            # save ebx
         pushl   %edi            # save edi
         movl    %esp, %ebp      # set base pointer
         subl    $12, %esp       # allocate memory
         movl    %esp, %edi
         movl    $12, %edx       # maximal string length
         movl    %edi, %ecx      # string address
         movl    $0, %ebx        # file descriptor
         movl    $3, %eax        # sys_read interrupt index
         int     $0x80           # kernel interrupt sys_read 
         addl    %eax, %ecx      # address of ...
         decl    %ecx            # last character
         # parse input
         movl    $0, %eax        # result accumulator
         cmpb    $'-, -12(%ebp)  # negative number?
         jne     readdigit
         incl    %edi            # skip '-'
readdigit:
         imull   $10, %eax       # multiply result by 10
         movl    $0, %edx        # copy digit ...
         movb    (%edi), %dl     # to dl
         subl    $'0, %edx       # convert ascii to value
         addl    %edx, %eax      # add value to result
         incl    %edi            # address of next digit
         cmpl    %edi, %ecx      # end of string?
         jg      readdigit
         cmpb    $'-, -12(%ebp)  # negative number?
         jne     rest
         negl    %eax            # negate result
rest:    movl    %ebp, %esp      # restore stack pointer
         popl    %edi            # restore edi
         popl    %ebx            # restore ebx
         popl    %ebp            # restore base pointer
         ret
         
writestr:
         pushl   %ebx            # save ebx
         movl    12(%esp), %edx  # third argument: string length
         movl    8(%esp), %ecx   # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         popl    %ebx            # restore ebx
         ret                     # return

writeln:
         pushl   %ebx            # save ebx
         pushl   $10             # push newline character
         movl    $1, %edx        # third argument: string length
         movl    %esp, %ecx    # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         addl    $4, %esp        # pop stack
         popl    %ebx            # restore ebx
         ret                     # return
         
exit:
         movl    4(%esp), %ebx   # first argument: error code 
         movl    $1, %eax        # sys_exit interrupt index
         int     $0x80           # kernel interrupt sys_exit
         